﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelLib
{
    /// <summary>
    /// 心跳检测
    /// </summary>
    public class HeartDetection : IDisposable
    {
        private AutoResetEvent bAutoEvent = new AutoResetEvent(false);
        private ManualResetEventSlim bPauseEvent = new ManualResetEventSlim(false);
        private ManualResetEventSlim bStopEvent = new ManualResetEventSlim(false);
        private Thread _thread;
        public event EventHandler OnDetected;
        public event EventHandler OnUnDetected;

        public HeartDetection(int maxTime)
        {
            MaxTime = maxTime;
            _thread = new Thread(DetctWork)
            {
                IsBackground = true,
                Priority = ThreadPriority.AboveNormal,
                Name = this.GetType().Name,
            };
        }

        public HeartDetection() : this(3000)
        {
        }

        public int MaxTime { get; set; }
        public void ReceivedBeate()
        {
            if (isDisposed)
                throw new ObjectDisposedException(this.GetType().Name);
            bAutoEvent.Set();
        }

        private void DetctWork()
        {
            while (true)
            {
                bPauseEvent.Wait();
                if (bStopEvent.Wait(0))
                    break;
                var ret = bAutoEvent.WaitOne(MaxTime);
                if (ret)
                {
                    //TODO:收到信号连接正常
                    OnDetected?.Invoke(null, null);
                }
                else
                {
                    //TODO:心跳检测超时
                    OnUnDetected?.Invoke(null, null);
                }
            }
        }

        public void Run()
        {
            if (isDisposed)
                throw new ObjectDisposedException(this.GetType().Name);
            bPauseEvent.Set();
            bStopEvent.Reset();
            if (_thread.ThreadState == ThreadState.Unstarted)
                _thread.Start();
            else if ((_thread.ThreadState & ThreadState.Stopped) == ThreadState.Stopped)
            {
                _thread = new Thread(DetctWork)
                {
                    IsBackground = true,
                    Priority = ThreadPriority.AboveNormal,
                    Name = this.GetType().Name,
                };
                _thread.Start();
            }
        }

        public void Pause()
        {
            if (isDisposed)
                throw new ObjectDisposedException(this.GetType().Name);
            bPauseEvent.Reset();
            bStopEvent.Reset();
        }

        public void Stop()
        {
            if (isDisposed)
                throw new ObjectDisposedException(this.GetType().Name);
            bPauseEvent.Set();
            bStopEvent.Set();
        }
        private bool isDisposed = false;
        public void Dispose()
        {
            if (isDisposed)
                return;
            isDisposed = true;
            Stop();
            bAutoEvent.Dispose();
            bPauseEvent.Dispose();
            bStopEvent.Dispose();
        }
    }
}
